home *** CD-ROM | disk | FTP | other *** search
/ Ultimedia 1 / Ultimedia 1.iso / tools / sonstiges / easysound / sound.c < prev    next >
C/C++ Source or Header  |  1994-08-04  |  25KB  |  621 lines

  1. /* Easy Sound */
  2.  
  3. /// "includes"
  4. #include <exec/types.h>
  5. #include <exec/memory.h>
  6. #include <devices/audio.h>
  7. #include <stdio.h>
  8. #include "EasySound.h"
  9.  
  10. #define CLOCK_CONSTANT 3579545
  11.  
  12. /* An IOAudio pointer to each sound channel: */
  13. struct IOAudio *IOA[4] = {
  14.     NULL, NULL, NULL, NULL
  15. };
  16.  
  17. typedef LONG Fixed;
  18. typedef struct {
  19.     ULONG oneShotHiSamples;     /* #samples in the high octave 1-shot part */
  20.     ULONG repeatHiSamples;      /* #samples in the high octave repeat part */
  21.     ULONG samplesPerHiCycle;    /* #samples/cycle in high octave, else 0   */
  22.     UWORD samplesPerSec;        /* Data sampling rate */
  23.     UBYTE ctOctave;             /* Number of octaves of waveforms */
  24.     UBYTE sCompression;         /* Data compression technique used */
  25.     Fixed volume;               /* Playback volume from 0 to 0x10000 */
  26. } Voice8Header;
  27.  
  28. /* Declare the functions we are going to use: */
  29.  
  30. BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
  31.                   BYTE priority, WORD delta_rate, UWORD repeat,
  32.                   ULONG start, ULONG time, BOOL wait);
  33.  
  34. void ESStopSound (UBYTE channel);
  35.  
  36. BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
  37.                    BYTE priority, struct SoundInfo *info, ULONG start,
  38.                    ULONG time);
  39.  
  40. void ESRemoveSound (struct SoundInfo *info);
  41.  
  42. struct SoundInfo *ESPrepareSound (STRPTR file);
  43.  
  44. UWORD ESLoadSound (STRPTR filename, struct SoundInfo *info);
  45.  
  46. ULONG ESGetSize (STRPTR filename);
  47.  
  48. ULONG ESSizeIFF (STRPTR filename);
  49.  
  50. UWORD ESReadIFF (STRPTR filename, struct SoundInfo *info);
  51.  
  52. BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr);
  53. ///
  54. /// "ESPlaySound"
  55. /* ESPlaySound()                                                         */
  56. /* ESPlaySound() plays one already prepared sound effect. You can decide */
  57. /* what volume, which channel, what rate, which priority, how many times */
  58. /* the sound should be played and so on...                               */
  59. /*                                                                       */
  60. /* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start,    */
  61. /*                           time, wait );                               */
  62. /*                                                                       */
  63. /* ok:    (BOOL) If the sound was played successfully TRUE is            */
  64. /*        returned, else FALSE.                                          */
  65. /*                                                                       */
  66. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure. This    */
  67. /*        pointer was returned by PrepareSound().                        */
  68. /*                                                                       */
  69. /* vol:   (UWORD) Volume, 0 to 64.                                       */
  70. /*                                                                       */
  71. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,          */
  72. /*        RIGHT1 or LEFT1)                                               */
  73. /*                                                                       */
  74. /* pri:   (BYTE) What priority should be used. See header file for a     */
  75. /*        complete list of recommended priorities.                       */
  76. /*                                                                       */
  77. /* drate: (WORD) Delta rate. When the sound is prepared, the record      */
  78. /*        rate is automatically stored in the SoundInfo structure,       */
  79. /*        so if you do not want to change the rate, write NORMALRATE.    */
  80. /*                                                                       */
  81. /* times: (UWORD) How many times the sound should be played. If you      */
  82. /*        want to play the sound forever, write NONSTOP. (To stop a      */
  83. /*        sound call the function StopSound().)                          */
  84. /*                                                                       */
  85. /* start: (ULONG) Where in the sound data we should start to play. (If   */
  86. /*        you want to start at the beginning of the sound data set start */
  87. /*        to 0.)                                                         */
  88. /*                                                                       */
  89. /* time:  (ULONG) For how long time the sound should be played. If you   */
  90. /*        want to play all of the sound data set time to 0.              */
  91. /*                                                                       */
  92. /* wait:  (BOOL) Set this parameter to WAIT if you want to wait for the  */
  93. /*        sound to be completed. If you set it to DO_NOT_WAIT, your      */
  94. /*        program will continue to run while the sound is played.        */
  95. /*        NOTE! Do not try to play a sound continiously (times set to    */
  96. /*        NONSTOP) and at the same time set this field to TRUE! The      */
  97. /*        request will then never be completed and your program will     */
  98. /*        come to a dead lock!!                                          */
  99.  
  100. BOOL ESPlaySound (struct SoundInfo *info, UWORD volume, UBYTE channel,
  101.                   BYTE priority, WORD delta_rate, UWORD times, ULONG start,
  102.                   ULONG time, BOOL wait) {
  103.     /* 
  104.      * Before we may play the sound, we must make sure that the sound is not 
  105.      * already being played. We will therefore call the function 
  106.      * ISStopSound(), in order to stop the sound if it is playing:       
  107.      */
  108.     ESStopSound (channel);
  109.  
  110.     if (ESPrepareIOA (CLOCK_CONSTANT/info->RecordRate + delta_rate, volume, times, channel, priority, info, start, time)) {
  111.  
  112.         BeginIO (IOA[channel]);
  113.         if (wait)
  114.             WaitIO (IOA[channel]);
  115.  
  116.         return (TRUE);          /* OK! */
  117.     }
  118.     else
  119.         return (FALSE);         /* ERROR! */
  120. }
  121. ///
  122. /// "ESStopSound"
  123. /* ESStopSound()                                                       */
  124. /* ESStopSound() will stop the specified audio channel from continuing */
  125. /* to play the sound. It will also close all devices and ports that    */
  126. /* have been opened, and deallocate some memory that have been         */
  127. /* allocated.                                                          */
  128. /*                                                                     */
  129. /* Synopsis: ISStopSound( channel );                                   */
  130. /* channel:  (UBYTE) The audio channel that should be stopped. (LEFT0, */
  131. /*           LEFT1, RIGHT0 or RIGHT1.)                                 */
  132.  
  133. void ESStopSound (UBYTE channel)
  134. {
  135.     /* Check if the IOAudio structure exist: */
  136.     if (IOA[channel]) {
  137.         /* 1. Stop the sound: */
  138.         AbortIO (IOA[channel]);
  139.  
  140.         /* 2. If there exist a Sound Device, close it: */
  141.         if (IOA[channel]->ioa_Request.io_Device)
  142.             CloseDevice (IOA[channel]);
  143.  
  144.         /* 3. If there exist a Message Port, delete it: */
  145.         if (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort)
  146.             DeletePort (IOA[channel]->ioa_Request.io_Message.mn_ReplyPort);
  147.  
  148.         /* 4. Remove the request block: */
  149.         DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
  150.  
  151.         /* 5. Set the pointer to NULL so we know that this */
  152.         /*    request has now been deleted:                */
  153.         IOA[channel] = NULL;
  154.     }
  155. }
  156.  
  157. ///
  158. /// "ESPrepareIOA"
  159. /* ESPrepareIOA()                                                       */
  160. /* ESPrepareIOA() allocates and initializes an IOAudio structure.       */
  161. /*                                                                      */
  162. /* Synopsis: ok = ISPrepareIOA( per, vol, cyc, cha, ptr, start, time ); */
  163. /*                                                                      */
  164. /* ok:    (BOOL) If the IOAudio structure was allocated and             */
  165. /*        initialized successfully, TRUE is returned, else FALSE.       */
  166. /* per:   (UWORD) Period time.                                          */
  167. /* vol:   (UWORD) Volume, 0 to 64.                                      */
  168. /* cyc:   (UWORD) How many times the sound should be played.            */
  169. /*        (0 : forever)                                                 */
  170. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,         */
  171. /*        RIGHT1 or LEFT1)                                              */
  172. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure.        */
  173. /* start: (ULONG) Where in the sound data we should start to play.      */
  174. /* time:  (ULONG) For how long time the sound should be played.         */
  175.  
  176. BOOL ESPrepareIOA (UWORD period, UWORD volume, UWORD cycles, UBYTE channel,
  177.                    BYTE priority, struct SoundInfo *info, ULONG start,
  178.                    ULONG time)
  179. {
  180.     /* Store error numbers here: */
  181.     BYTE error;
  182.  
  183.     /* Declare a pointer to a MsgPort structure: */
  184.     struct MsgPort *port;
  185.  
  186.     /* Get a reply port: (No name, normal priority) */
  187.     port = (struct MsgPort *)
  188.         CreatePort (NULL, 0);
  189.  
  190.     /* Did we get a reply port? */
  191.     if (!port) {
  192.         /* Bad news! We did not get a reply port. */
  193.  
  194.         /* Return with an error value: */
  195.         return (FALSE);
  196.     }
  197.  
  198.     /* Create an IOAudio request: */
  199.     IOA[channel] = (struct IOAudio *)
  200.         CreateExtIO (port, sizeof (struct IOAudio));
  201.  
  202.     /* Could we allocate enough memory? */
  203.     if (!IOA[channel]) {
  204.         /* Tough luck! We did not get a request block. */
  205.  
  206.         /* Close the reply port: */
  207.         DeletePort (port);
  208.  
  209.         /* Return with an error value: */
  210.         return (FALSE);
  211.     }
  212.  
  213.     /* Initialize the IOAudion structure: */
  214.  
  215.     /* Set priority: */
  216.     IOA[channel]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
  217.  
  218.     /* Set channel: (This program tries to reserve one specific */
  219.     /* audio channel. It does not support an allocation array   */
  220.     /* with several options.)                                   */
  221.     info->channel_bit = 1 << channel;
  222.  
  223.     /* Give the request block a pointer to our simple allocation array: */
  224.     IOA[channel]->ioa_Data = &(info->channel_bit);
  225.  
  226.     /* Set the length of our allocation array: */
  227.     IOA[channel]->ioa_Length = sizeof (UBYTE);
  228.  
  229.     /* Open Audio Device: */
  230.     error = OpenDevice (AUDIONAME, 0, IOA[channel], 0);
  231.  
  232.     /* Have wee successfully opened it? */
  233.     if (error) {
  234.         /* Hard times! Could not open the device! */
  235.  
  236.         /* Delete the request block: */
  237.         DeleteExtIO (IOA[channel], sizeof (struct IOAudio));
  238.  
  239.         /* Close the reply port: */
  240.         DeletePort (port);
  241.  
  242.         /* Set audio pointer to NULL so we know that */
  243.         /* we do not have any request block here:    */
  244.         IOA[channel] = NULL;
  245.  
  246.         /* Return with an error value: */
  247.         return (FALSE);         /* ERROR! */
  248.     }
  249.  
  250.     /* We now have a reply port, a request block, one  */
  251.     /* audio channel reserved and the audio device has */
  252.     /* been opened. Prepare to play:                   */
  253.  
  254.     /* Initialize the request block with the users requirements: */
  255.     IOA[channel]->ioa_Request.io_Flags = ADIOF_PERVOL;
  256.  
  257.     /* We want to play sound (write data to the audio device): */
  258.     IOA[channel]->ioa_Request.io_Command = CMD_WRITE;
  259.  
  260.     /* Set period value: */
  261.     IOA[channel]->ioa_Period = period;
  262.  
  263.     /* Set volume: */
  264.     IOA[channel]->ioa_Volume = volume;
  265.  
  266.     /* Number of times the sound wave should be played: */
  267.     IOA[channel]->ioa_Cycles = cycles;
  268.  
  269.     /* If the user has specified a play time we use */
  270.     /* it, else we play the complete sound:         */
  271.     if (time)
  272.         IOA[channel]->ioa_Length = time;
  273.     else
  274.         IOA[channel]->ioa_Length = info->FileLength;
  275.  
  276.     /* Set start position in the waveform: */
  277.     IOA[channel]->ioa_Data = info->SoundBuffer + start;
  278.  
  279.     /* Everything has been prepared, return with OK: */
  280.     return (TRUE);
  281. }
  282. ///
  283. /// "ESRemoveSound"
  284. /* ESRemoveSound()                                                        */
  285. /* ESRemoveSound() will stop playing the sound, and deallocate all memory */
  286. /* that was allocated by the PrepareSound() function. Before your program */
  287. /* terminates, all soundeffects that have been prepared, MUST be removed. */
  288. /*                                                                        */
  289. /* IMPORTANT! Each channel that is currently playing the sound must be    */
  290. /* stopped before you may remove the sound!!!! (Use the ESStopSound()     */
  291. /* function.)                                                             */
  292. /*                                                                        */
  293. /* Synopsis: ESRemoveSound( pointer );                                    */
  294. /*                                                                        */
  295. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.       */
  296.  
  297. void ESRemoveSound (struct SoundInfo *info)
  298. {
  299.     /* IMPORTANT! The sound must have been */
  300.     /* stopped before you may remove it!!! */
  301.  
  302.     /* Have we allocated a SoundInfo structure? */
  303.     if (info) {
  304.         /* Deallocate the sound buffer: */
  305.         FreeMem (info->SoundBuffer, info->FileLength);
  306.  
  307.         /* Deallocate the SoundInfo structure: */
  308.         FreeMem (info, sizeof (struct SoundInfo));
  309.         info = NULL;
  310.     }
  311. }
  312.  
  313. ///
  314. /// "ESPrepareSound"
  315. /* ESPrepareSound()
  316.  
  317. ESPrepareSound() loads a sampled sound file (IFF or FutureSound) into a 
  318. buffer that is automatically allocated. All information about the sound 
  319. (record rate, length, buffersize etc) is put into an SoundInfo structure. 
  320. If ESPrepareSound() has successfully prepared the sound it returns a 
  321. pointer to a SoundInfo structure, otherwise it returns NULL.
  322.  
  323. Synopsis: pointer = ESPrepareSound( filename );
  324.  
  325. pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.
  326.  
  327. filename: (STRPTR) Pointer to a string containing the name of the
  328.           sound file. For example "df0:Explosion.snd".
  329. */
  330.  
  331. struct SoundInfo *ESPrepareSound (STRPTR file) {
  332.  
  333.     struct SoundInfo *info;
  334.  
  335.     /* 
  336.      * Allocate memory for a SoundInfo structure: (The memory can be of 
  337.      * any type, and should be cleared.)            
  338.      */
  339.     info = (struct SoundInfo *)AllocMem (sizeof (struct SoundInfo), MEMF_CLEAR);
  340.     if (!info) {
  341.         return (NULL);
  342.     }
  343.  
  344.     /* 
  345.      * Get the size of the sound file, and store it in the SoundInfo 
  346.      * structure:            
  347.      */
  348.     info->FileLength = ESGetSize (file);
  349.     if (info->FileLength == 0) {
  350.         FreeMem (info, sizeof (struct SoundInfo));
  351.         return (NULL);
  352.     }
  353.  
  354.     /* 
  355.      * Allocate enough memory for the sampled sound, and store a pointer to 
  356.      * the buffer in the SoundInfo structure: (Remember that sound data must 
  357.      * be in chip memory.)                   
  358.      */
  359.     info->SoundBuffer = (BYTE *) AllocMem (info->FileLength, MEMF_CHIP | MEMF_CLEAR);
  360.     if (!info->SoundBuffer) {
  361.         FreeMem (info, sizeof (struct SoundInfo));
  362.         return (NULL);
  363.     }
  364.  
  365.     info->RecordRate = ESLoadSound (file, info);
  366.     if (info->RecordRate == 0) {
  367.         FreeMem (info->SoundBuffer, info->FileLength);
  368.         FreeMem (info, sizeof (struct SoundInfo));
  369.         return (NULL);
  370.     }
  371.  
  372.     /* 
  373.      * The sound has now successfully been loaded! 
  374.      */
  375.  
  376.     /* 
  377.      * Old FutureSound files were saved in kHz. If the record rate is less 
  378.      * than one hundered, we know it is an old FutureSound file, and simply 
  379.      * multiply the rate with one thousand:       
  380.      */
  381.     if (info->RecordRate < 100)
  382.         info->RecordRate *= 1000;
  383.  
  384.     /* Return a pointer to the SoundInfo structure: */
  385.     return (info);
  386. }
  387. ///
  388. /// "ESLoadSound"
  389. /* ESLoadSound()                                                       */
  390. /* ESLoadSound() will load sampled sound that was either saved in IFF  */
  391. /* or FutureSound format.                                              */
  392. /*                                                                     */
  393. /* Synopsis: rate = ESLoadSound( filename, pointer );                  */
  394. /*                                                                     */
  395. /* rate:     (UWORD) The record rate is returned if the sound was      */
  396. /*           successfully loaded, else 0.                              */
  397. /*                                                                     */
  398. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  399. /*           sound file. For example "df0:Explosion.snd".              */
  400. /*                                                                     */
  401. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.    */
  402.  
  403. UWORD ESLoadSound (STRPTR filename, struct SoundInfo * info)
  404. {
  405.     FILE *file_ptr;             /* Pointer to a file. */
  406.     ULONG length;               /* Data Length. */
  407.     UWORD record_rate;          /* Record rate. */
  408.  
  409.     /* Check if it is an IFF File: */
  410.     if (ESSizeIFF (filename)) {
  411.         /* Yes, it is an IFF file. Read it: */
  412.         return (ESReadIFF (filename, info));
  413.     }
  414.     else {
  415.         /* No, then it is probably a FutureSound file. */
  416.         /* Open the file so we can read it:            */
  417.         if ((file_ptr = fopen (filename, "r")) == 0)
  418.             return (0);         /* ERROR! Could not open the file! */
  419.  
  420.         /* Read the data length: */
  421.         if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
  422.             /* ERROR! Could not read the data length! */
  423.             /* Close the file, and return zero:       */
  424.             fclose (file_ptr);
  425.             return (0);
  426.         }
  427.  
  428.         /* Read the record rate: */
  429.         if (fread ((char *) &record_rate, sizeof (UWORD), 1, file_ptr) == 0) {
  430.             /* ERROR! Could not read the record rate! */
  431.             /* Close the file, and return zero:       */
  432.             fclose (file_ptr);
  433.             return (0);
  434.         }
  435.  
  436.         /* Read the sampled sound data into the buffer: */
  437.         if (fread ((char *) info->SoundBuffer, length, 1, file_ptr) == 0) {
  438.             /* ERROR! Could not read the data!  */
  439.             /* Close the file, and return zero: */
  440.             fclose (file_ptr);
  441.             return (0);
  442.         }
  443.  
  444.         /* Close the file: */
  445.         fclose (file_ptr);
  446.  
  447.         /* Return the record rate: */
  448.         return (record_rate);
  449.     }
  450. }
  451. ///
  452. /// "ESGetSize"
  453. /* ESGetSize()                                                        */
  454. /* ESGetSize() returns the size of the file which was saved in either */
  455. /* IFF or FutureSound format.                                         */
  456. /*                                                                    */
  457. /* Synopsis: length = ESGetSize( filename );                          */
  458. /*                                                                    */
  459. /* length:   (ULONG) Data length.                                     */
  460. /*                                                                    */
  461. /* filename: (STRPTR) Pointer to a string containing the name of the  */
  462. /*           sound file. For example "df0:Explosion.snd".             */
  463.  
  464. ULONG ESGetSize (STRPTR filename)
  465. {
  466.     FILE *file_ptr;             /* Pointer to a file. */
  467.     ULONG length;               /* Data length. */
  468.  
  469.     /* Check if it is an IFF File: */
  470.     if ((length = ESSizeIFF (filename)) == 0) {
  471.         /* No, then it is probably a FutureSound file. */
  472.         /* Open the file so we can read it:            */
  473.         if ((file_ptr = fopen (filename, "r")) == 0)
  474.             return (0);         /* ERROR! Could not open the file! */
  475.  
  476.         /* Read the data length: */
  477.         if (fread ((char *) &length, sizeof (ULONG), 1, file_ptr) == 0) {
  478.             /* ERROR! Could not read the data length! */
  479.             /* Close the file, and return zero:       */
  480.             fclose (file_ptr);
  481.             return (0);
  482.         }
  483.  
  484.         /* Close the file: */
  485.         fclose (file_ptr);
  486.     }
  487.     return (length);
  488. }
  489. ///
  490. /// "ESSizeIFF"
  491. /* ESSizeIFF()                                                       */
  492. /* ESSizeIFF() returns the size of an IFF file, or zero if something */
  493. /* went wrong (for example, It was not an IFF file).                 */
  494. /*                                                                   */
  495. /* Synopsis: length = ESSizeIFF( filename );                         */
  496. /*                                                                   */
  497. /* length:   (ULONG) Data length.                                    */
  498. /*                                                                   */
  499. /* filename: (STRPTR) Pointer to a string containing the name of the */
  500. /*           IFF file. For example "df0:Explosion.snd".              */
  501.  
  502. ULONG ESSizeIFF (STRPTR filename)
  503. {
  504.     FILE *file_ptr;             /* Pointer to a file. */
  505.     STRPTR empty_string = "    ";       /* Four spaces. */
  506.     LONG dummy;                 /* A dummy variable. */
  507.     Voice8Header Header;        /* Voice8Header structure. */
  508.  
  509.     /* Try to open the file: */
  510.     if (file_ptr = fopen (filename, "r")) {
  511.         fread ((char *) empty_string, 4, 1, file_ptr);
  512.         if (strcmp (empty_string, "FORM") == 0) {
  513.             /* Read twice: */
  514.             fread ((char *) empty_string, 4, 1, file_ptr);
  515.             fread ((char *) empty_string, 4, 1, file_ptr);
  516.  
  517.             /* Check if it is a "8SVX" file, or not: */
  518.             if (strcmp (empty_string, "8SVX") == 0) {
  519.                 ESMoveTo ("VHDR", file_ptr);
  520.                 fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
  521.                 fread ((char *) &Header, sizeof (Header), 1, file_ptr);
  522.  
  523.                 /* Close the file, and return the length: */
  524.                 fclose (file_ptr);
  525.                 return (Header.oneShotHiSamples + Header.repeatHiSamples);
  526.             }
  527.         }
  528.         /* Close the file: */
  529.         fclose (file_ptr);
  530.     }
  531.     /* Return zero: (ERROR) */
  532.     return (0);
  533. }
  534. ///
  535. /// "ESReadIFF"
  536. /* ESReadIFF()                                                           */
  537. /* ESReadIFF() reads an IFF file into the buffer, and returns the record */
  538. /* rate.                                                                 */
  539. /*                                                                       */
  540. /* Synopsis: rate = ESReadIFF( filename, pointer );                      */
  541. /*                                                                       */
  542. /* rate:     (UWORD) The record rate is returned if the sound was        */
  543. /*           successfully loaded, else 0.                                */
  544. /*                                                                       */
  545. /* filename: (STRPTR) Pointer to a string containing the name of the     */
  546. /*           sound file. For example "df0:Explosion.snd".                */
  547. /*                                                                       */
  548. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.      */
  549.  
  550. UWORD ESReadIFF (STRPTR filename, struct SoundInfo * info)
  551. {
  552.     FILE *file_ptr;             /* Pointer to a file. */
  553.     STRPTR empty_string = "    ";       /* Four spaces. */
  554.     LONG dummy;                 /* A dummy variable. */
  555.     Voice8Header Header;        /* Voice8Header structure. */
  556.  
  557.     /* Try to open the file: */
  558.     if (file_ptr = fopen (filename, "r")) {
  559.         fread ((char *) empty_string, 4, 1, file_ptr);
  560.         if (strcmp (empty_string, "FORM") == 0) {
  561.             /* Read twice: */
  562.             fread ((char *) empty_string, 4, 1, file_ptr);
  563.             fread ((char *) empty_string, 4, 1, file_ptr);
  564.  
  565.             /* Check if it is a "8SVX" file, or not: */
  566.             if (strcmp (empty_string, "8SVX") == 0) {
  567.                 ESMoveTo ("VHDR", file_ptr);
  568.                 fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
  569.                 fread ((char *) &Header, sizeof (Header), 1, file_ptr);
  570.  
  571.                 ESMoveTo ("BODY", file_ptr);
  572.                 fread ((char *) &dummy, sizeof (LONG), 1, file_ptr);
  573.                 fread ((char *) info->SoundBuffer, Header.oneShotHiSamples +
  574.                        Header.repeatHiSamples, 1, file_ptr);
  575.  
  576.                 /* Close the file, and return the record rate: */
  577.                 fclose (file_ptr);
  578.                 return (Header.samplesPerSec);
  579.             }
  580.         }
  581.         /* Close the file: */
  582.         fclose (file_ptr);
  583.     }
  584.     /* Return zero: (ERROR) */
  585.     return (0);
  586. }
  587. ///
  588. /// "ESMoveTo"
  589. /* ESMoveTo()                                                  */
  590. /* ESMoveTo() walks through an IFF file, and looks for chunks. */
  591. /*                                                             */
  592. /* Synopsis: ESMoveTo( chunk, file_ptr );                      */
  593. /*                                                             */
  594. /* chunk:    (STRPTR) The chunk we want to get to.             */
  595. /*                                                             */
  596. /* file_ptr: (FILE *) Pointer to an already opened file.       */
  597.  
  598. BOOL ESMoveTo (STRPTR check_string, FILE * file_ptr)
  599. {
  600.     STRPTR empty_string = "    ";       /* Four spaces. */
  601.     int skip, loop;             /* How much data should be skiped. */
  602.     LONG dummy;                 /* A dummy variable. */
  603.  
  604.     /* As long as we have not reached the EOF, continue: */
  605.     while (!feof (file_ptr)) {
  606.         fread ((char *) empty_string, 4, 1, file_ptr);
  607.  
  608.         /* Have we found the right chunk? */
  609.         if (strcmp (check_string, empty_string) == 0)
  610.             return (0);         /* YES! Return nothing. */
  611.  
  612.         /* Move foreward: */
  613.         fread ((char *) &skip, sizeof (LONG), 1, file_ptr);
  614.         for (loop = 0; loop < skip; loop++)
  615.             fread ((char *) &dummy, 1, 1, file_ptr);
  616.     }
  617. }
  618.  
  619. ///
  620.  
  621.